package com.rc.saas.base;

import com.rc.saas.mini.common.constant.HttpConstant;
import com.rc.saas.mini.common.constant.SessionConstants;
import com.rc.saas.mini.minip.token.RedisTokenLoader;
import com.rc.saas.mini.minip.vo.LoginInfoVo;
import com.rc.saas.mini.model.hlhtsk.HlhtskTenant;
import com.rc.saas.mini.service.hlhtsk.HlhtskTenantService;
import com.rc.saas.mini.service.member.MemberInfoService;
import com.rc.saas.mini.utils.PubFetchTool;
import com.rc.saas.mini.vo.cec.StdRequest;
import com.rc.saas.mini.weixin.RedisWxConfiguration;
import com.rc.saas.mini.weixin.RedisWxConfigurationLoader;
import com.rc.saas.mini.weixin.WxSessionInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 默认是单例模式,当controller被实例化之后，整个容器中只会有一个实例
 * @author wangzhengwei
 * @create 2021/4/15
 */
public class MinipBaseController implements ApplicationContextAware {
    private static Logger logger = LogManager.getLogger(MinipBaseController.class);

    private ApplicationContext ac;


    @Autowired
    private RedisTokenLoader redisTokenLoader;

    private static final String REDIS_ACCESS_TOKEN_KEY_TEMP = "saas:{0}:access_token";

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RedisWxConfigurationLoader redisWxConfigurationLoader;

    @Autowired
    private HlhtskTenantService hlhtskTenantService;
    @Autowired
    private MemberInfoService memberInfoService;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ac = applicationContext;
    }

    protected ApplicationContext getApplicationContext() {
        return ac;
    }

    protected <T> T getBean(String name) throws BeansException {
        return (T) ac.getBean(name);
    }

    /**
     * 读取会话中的toekn,在TokenInterceptor设置,如果没登录不会有
     * 有效期受控于maxInactiveIntervalInSeconds
     * @return
     */
    protected String readSessionToken(HttpSession session) {
        //logger.info("request.getHeader():{},:{}", request.getHeader("jsessionid"), request.getCookies());
        //logger.info("request.getCookies():{}:{}", request.getCookies(), request.getCookies());

        //在TokenInterceptor设置
        return (String) session.getAttribute(SessionConstants.SESSION_TOKEN);
    }

    /**
     * 取token管理器
     * @return
     */
    protected RedisTokenLoader getRedisTokenLoader() {
        return redisTokenLoader;
    }

    /**
     * 读取会话中的token去取redis缓存信息
     * 有效期受控于redis.timeout
     *
     * @return
     */
    //protected LoginInfoVo readLoginInfo(HttpSession session) {
    //    //logger.info("request.getHeaderNames():{},:{}", request.getHeaderNames(), request.getCookies());
    //    //logger.info("request.getCookies():{}:{}", request.getCookies(), request.getCookies());
    //
    //    String token = readSessionToken(session);
    //    logger.info("readLoginInfo session token :{}", token);
    //
    //    if (StringUtils.isBlank(token)) {
    //        logger.warn("readLoginInfo session token ID 失效:{}", token);
    //        return null;
    //    }
    //
    //    return redisTokenLoader.readToken(token);
    //}
    protected LoginInfoVo readLoginInfo(HttpServletRequest request) {
        //logger.info("request.getHeaderNames():{},:{}", request.getHeaderNames(), request.getCookies());
        //logger.info("request.getCookies():{}:{}", request.getCookies(), request.getCookies());
        String authorization = request.getHeader(HttpConstant.AUTHORIZATION);
        if(authorization==null){
            return null;
        }
        String token = authorization.substring(7);
        logger.info("readLoginInfo  token :{}", token);

        if (StringUtils.isBlank(token)) {
            logger.warn("readLoginInfo  token ID 失效:{}", token);
            return null;
        }

        return redisTokenLoader.readToken(token);
    }

    /**
     * 读取公众号Redis中的非敏感信息
     */
    protected WxSessionInfo getWxSessionInfo(LoginInfoVo loginInfoVo) {


        if (StringUtils.isNotBlank(loginInfoVo.getMiniOriginalid())) {
            return getWxSessionInfo(loginInfoVo.getMiniOriginalid(), loginInfoVo);
        } else {
            return null;
        }
    }

    /**
     * 读取公众号Redis中的非敏感信息
     */
    protected WxSessionInfo getWxSessionInfo(String originalid, LoginInfoVo loginInfoVo) {
        //String session_weixin_originalid = (String) session.getAttribute(SessionConstants.SESSION_WEIXIN_ORIGINALID);
        //String session_weixin_state = (String) session.getAttribute(SessionConstants.SESSION_WEIXIN_STATE);
        //logger.info("getWxSessionInfo,session_weixin_originalid:{}", session_weixin_originalid);

        //String tenantCode = (String) session.getAttribute(SessionConstants.SESSION_TENANT);
        //String nickname = (String) session.getAttribute(SessionConstants.SESSION_NICKNAME);
        String openid = loginInfoVo.getMiniOpenid();
        String unionid = loginInfoVo.getMiniUnionid();

        if (StringUtils.isBlank(openid)) {
            return null;
        } else {
            //根据原始ID查找启动时加载的公众号配置信息，但没有OPENID之类的个人信息
            WxSessionInfo wxSessionInfo = new WxSessionInfo();
            RedisWxConfiguration redisWxConfiguration = redisWxConfigurationLoader.get(loginInfoVo.getMiniOriginalid());
            if (redisWxConfiguration != null) {
                //wxSessionInfo.setRedisWxConfiguration(redisWxConfiguration);

                wxSessionInfo.setOriginalid(loginInfoVo.getMiniOriginalid());
                wxSessionInfo.setMchId(redisWxConfiguration.getMchId());
                wxSessionInfo.setTenantPrefix(redisWxConfiguration.getTenantPrefix());
                wxSessionInfo.setAppId(redisWxConfiguration.getAppId());

                //运营商
                wxSessionInfo.setTenantCode(redisWxConfiguration.getTenantCode());
                //session.setAttribute(SessionConstants.SESSION_TENANT, wxSessionInfo.getTenantCode());

                ////NICKNAME
                //wxSessionInfo.setNickname(nickname);
                //OPENID
                wxSessionInfo.setOpenid(openid);
                //UNIONID
                wxSessionInfo.setUnionid(unionid);
            }

            logger.info("getWxSessionInfo,tenantCode:{},openid:{},unionid:{}", wxSessionInfo.getTenantCode(), openid, unionid);

            return wxSessionInfo;
        }
    }


    /**
     * 封装KyConfig、数据、加密
     */
    protected String encryptData(String respData, String tenantCode) {
        HlhtskTenant hlhtskTenant = hlhtskTenantService.selectByTenantCode(tenantCode);
        //没有内联时，tenantCode=hlhtTenantCode
        //HlhtskTenant hlhtskTenant = hlhtskTenantService.selectBetweenTenantCode(tenantCode, hlhtTenantCode);

        String data = PubFetchTool.genDDEncodeData(hlhtskTenant, respData);
        return data;
    }

    /**
     * 封装请求信息
     */
    protected StdRequest genSuccessReq(String data, String tenantCode) {
        StdRequest resp = new StdRequest();
        resp.setData(data);
        resp.setSeq(tenantCode);
        return resp;
    }

    ///**
    // * 初始化weixin对象
    // * @param redisWxConfiguration
    // */
    //private synchronized Weixin initWeixin(RedisWxConfiguration redisWxConfiguration) throws WeixinException {
    //    if (weixin == null) {
    //        //从Redis中加载配置信息
    //        logger.info("初始化weixin对象,getAppId:{},Originalid:{},Secret:{}", redisWxConfiguration.getAppId(), redisWxConfiguration.getOriginalid(), redisWxConfiguration.getSecret());
    //
    //        //初始化weixin对象
    //        Weixin newWeixin = new Weixin(redisWxConfiguration.getOriginalid(), redisWxConfiguration.getAppId(), redisWxConfiguration.getSecret());
    //        return newWeixin;
    //    } else {
    //        logger.info("weixin对象已初始化,Access_token:{}", weixin.getToken().getAccess_token());
    //        return weixin;
    //    }
    //}
    //
    ///**
    // * 初始化WxJSConfig对象
    // * @param wxSessionInfo
    // * @param model
    // * @param request
    // * @param apiList
    // */
    //protected void initWxConfig(WxSessionInfo wxSessionInfo, Model model, HttpServletRequest request, String[] apiList) {
    //    try {
    //        //initWxConfig(wxSessionInfo, model, request, new String[]{"getLocation", "openLocation", "translateVoice"});
    //        //从Redis中加载配置信息
    //        RedisWxConfiguration redisWxConfiguration = redisWxConfigurationLoader.get(wxSessionInfo.getOriginalid());
    //        //logger.info("初始化weixin对象,getAppId:{},Originalid:{},Secret:{}", redisWxConfiguration.getAppId(), redisWxConfiguration.getOriginalid(), redisWxConfiguration.getSecret());
    //
    //        //初始化weixin对象
    //        //Weixin weixin = new Weixin(redisWxConfiguration.getOriginalid(), redisWxConfiguration.getAppId(), redisWxConfiguration.getSecret());
    //        Weixin newWeixin = initWeixin(redisWxConfiguration);
    //
    //        //获取Token对象并保存到Redis中,如果返回null会自动刷新
    //        Token token = newWeixin.getToken();
    //        //获取票据并保存到Redis中,如果返回null会自动刷新
    //        Ticket jsApiTicket = newWeixin.getJsApiTicket();
    //
    //        //使用jsApiTicket创建WxJSConfig
    //        WxJSConfig config = new WxJSConfig(false, redisWxConfiguration.getAppId(), jsApiTicket.getTicket(), currentUrl(request), apiList);
    //        String jsons = JSON.toJSONString(config);
    //        model.addAttribute("wxConfig", jsons);
    //
    //        logger.info("-------------- 微信配置开始 ---------------------------");
    //        logger.info("微信登陆信息 ：Access_token [{}]", token.getAccess_token());
    //        logger.info("微信登陆信息 ：Access_token有效时间 [{}] 秒", token.getExpires_in());
    //        logger.info("微信登陆信息 ：操作JSAPI 票据 [{}]", jsApiTicket.getTicket());
    //        logger.info("微信登陆信息 ：JSAPI有效时间 [{}] 秒", jsApiTicket.getExpires_in());
    //        logger.info("微信登陆信息 ：URL :{}", currentUrl(request));
    //        logger.info("微信登陆信息 ：wxConfig,:{}", jsons);
    //        logger.info("-------------- 微信配置结束 ---------------------------");
    //
    //        //this.weixin = newWeixin;
    //    } catch (WeixinException e) {
    //        if (e.getMessage().contains("40001")) {
    //            //获取 access_token 时 AppSecret 错误，或者 access_token 无效。请开发者认真比对 AppSecret 的正确性，或查看是否正在为恰当的公众号调用接口
    //            //删除 access_token 下次自动刷新
    //            //redisTemplate.delete(MessageFormat.format(REDIS_ACCESS_TOKEN_KEY_TEMP, originalid));
    //            redisTemplate.delete(MessageFormat.format(REDIS_ACCESS_TOKEN_KEY_TEMP, wxSessionInfo.getOriginalid()));
    //        }
    //        logger.error("初始化WxJSConfig对象出现异常", e);
    //    }
    //}
    //
    ///**
    // * 生成WxConfig并返回给前端微信JS
    // * @param wxSessionInfo
    // * @param request
    // * @param apiList
    // */
    //protected WxJSConfig readWxJSConfig(WxSessionInfo wxSessionInfo, HttpServletRequest request, String[] apiList) {
    //    try {
    //        //logger.info("初始化weixin对象,getAppId:{},getJsApiTicket:{}", redisWxConfiguration.getAppId(), weixinTemplate.getJsApiTicket());
    //        RedisWxConfiguration redisWxConfiguration = redisWxConfigurationLoader.get(wxSessionInfo.getOriginalid());
    //
    //        //初始化weixin对象
    //        //Weixin weixin = new Weixin(redisWxConfiguration.getOriginalid(), redisWxConfiguration.getAppId(), redisWxConfiguration.getSecret());
    //        Weixin newWeixin = initWeixin(redisWxConfiguration);
    //
    //        //获取票据,如果返回null会自动刷新
    //        Ticket jsApiTicket = newWeixin.getJsApiTicket();
    //
    //        //使用jsApiTicket创建WxJSConfig
    //        WxJSConfig config = new WxJSConfig(false, redisWxConfiguration.getAppId(), jsApiTicket.getTicket(), currentUrl(request), apiList);
    //        return config;
    //    } catch (Exception e) {
    //        logger.error("加载WxJSConfig出现异常", e);
    //    }
    //    return null;
    //}

    /**
     * 返回当前url
     * @param request 当前请求
     * @return 当前url
     */
    private String currentUrl(HttpServletRequest request) {
        String fullPath = (request.getScheme().indexOf("s")!=-1?request.getScheme():request.getScheme()+"s")
                + "://" + request.getServerName() + request.getRequestURI();
        if (StringUtils.isNotBlank(request.getQueryString())) {
            fullPath += "?" + request.getQueryString();
        }
        return fullPath;
    }
}
